﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace CloseDisplay
{
    /// <summary>
    /// 空闲监控器（封装全局鼠标键盘钩子 + Idle Timer）
    /// </summary>
    public class IdleMonitor : IDisposable
    {
        private Timer idleTimer;
        private int idleSeconds = 0;
        private int idleThreshold;

        public event EventHandler IdleElapsed;  // 达到闲置阈值时触发
        public event EventHandler<int> IdleTick; // 每秒回调一次（传递已经闲置的秒数）
        private LockScreenWatcher watcher = new LockScreenWatcher();

        public string IsLocked => watcher.IsLocked ? "锁屏" : "解锁";

        public int IdleThreshold
        {
            get => idleThreshold;
            set
            {
                if (value <= 0) throw new ArgumentException("IdleThreshold 必须大于 0");
                idleThreshold = value;
            }
        }

        public IdleMonitor(int thresholdSeconds = 10)
        {
            IdleThreshold = thresholdSeconds;

            idleTimer = new Timer();
            idleTimer.Interval = 1000;
            idleTimer.Tick += IdleTimer_Tick;

            // 安装钩子
            HookManager.KeyDown += OnKeyActivity;
            HookManager.MouseMove += OnMouseActivity;
            HookManager.MouseClick += OnMouseActivity; 

            watcher.OnLock += () =>
            {
                Tools.TurnOffMonitor();//锁屏时关闭显示器
                Start(); // 锁屏是 开始监控
            };

            watcher.OnUnlock += () =>
            {
                Stop(); // 解锁是 停止监控
            };
        }

        public void Start()
        {
            idleSeconds = 0;
            idleTimer.Start();
        }

        public void Stop()
        {
            idleTimer.Stop();
        }

        private void OnKeyActivity(object sender, KeyEventArgs e)
        {
            ResetIdle(8); // 键盘操作改为 30 秒
        }

        private void OnMouseActivity(object sender, EventArgs e)
        {
            ResetIdle(5); // 鼠标操作改为 10 秒
        }

        private void ResetIdle(int newThreshold)
        {
            if (watcher.IsLocked)
            {
                IdleThreshold = newThreshold;
                idleSeconds = 0;
                idleTimer.Stop();
                idleTimer.Start();
            }
        }

        private void IdleTimer_Tick(object sender, EventArgs e)
        {
            idleSeconds++;
            IdleTick?.Invoke(this, idleSeconds);

            if (idleSeconds == IdleThreshold)
            {
                IdleElapsed?.Invoke(this, EventArgs.Empty);
            }
        }

        public void Dispose()
        {
            idleTimer?.Dispose();
            Stop();
        }
    }

    /// <summary>
    /// 全局鼠标和键盘钩子管理器
    /// </summary>
    public static class HookManager
    {
        public static event KeyEventHandler KeyDown;
        public static event MouseEventHandler MouseMove;
        public static event MouseEventHandler MouseClick;

        [DllImport("user32.dll")]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll")]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll")]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        private delegate IntPtr LowLevelProc(int nCode, IntPtr wParam, IntPtr lParam);

        private static IntPtr _keyboardHookID = IntPtr.Zero;
        private static IntPtr _mouseHookID = IntPtr.Zero;

        private static LowLevelProc _keyboardProc = KeyboardHookCallback;
        private static LowLevelProc _mouseProc = MouseHookCallback;

        static HookManager()
        {
            _keyboardHookID = SetHook(_keyboardProc, 13); // WH_KEYBOARD_LL
            _mouseHookID = SetHook(_mouseProc, 14);       // WH_MOUSE_LL
        }

        private static IntPtr SetHook(LowLevelProc proc, int hookId)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(hookId, proc,
                    GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        private static IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0)
                KeyDown?.Invoke(null, new KeyEventArgs(Keys.None));

            return CallNextHookEx(_keyboardHookID, nCode, wParam, lParam);
        }

        private static IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                MouseMove?.Invoke(null, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0));
                MouseClick?.Invoke(null, new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
            }
            return CallNextHookEx(_mouseHookID, nCode, wParam, lParam);
        }
    }
}
